字数
571 字
阅读时间
3 分钟
暗色模式-实现支持跟随系统自动变化与手动设置的明暗模式切换
明暗跟随系统的实现方式
跟随系统的明暗模式可以通过媒体查询 prefers-color-scheme: {dark|light}
去实现,例如下面这样:
less
@media (prefers-color-scheme: dark) {
color: #FFFFFF;
background-color: #171717;
}
实现支持手动修改
但是如果我们要同时支持用户在页面上手动修改,则需要通过 JavaScript 去控制,使用 matchMedia
函数可以在 JS 脚本中进行媒体查询来获取当前的 prefers-color-schem
状态,并根据条件修改 body 的 class 加上 .theme-dark
类。具体代码实现如下:
util/darkMode.ts
typescript
// util/darkMode.ts
type ColorMode = 'auto' | 'light' | 'dark'
const classDarkName = 'theme-dark'
const cookieName = 'color-mode'
const body = document.getElementsByTagName('body')[0] as HTMLBodyElement
/** 检查夜间模式是否需要生效 */
export function checkDarkMode() {
const mode = window.localStorage && window.localStorage.getItem(cookieName)
// 自动模式
if (!mode || mode === 'auto') {
if (typeof matchMedia === 'function' && matchMedia('(prefers-color-scheme: dark)').matches)
body.classList.add(classDarkName)
else
body.classList.remove(classDarkName)
}
// 手动模式
else {
if (mode === 'dark')
body.classList.add(classDarkName)
else
body.classList.remove(classDarkName)
}
}
/** 切换明暗主题 */
export function setColorMode(mode: ColorMode) {
window.localStorage && window.localStorage.setItem(cookieName, mode)
checkDarkMode()
}
然后在界面加载完成后注册 prefers-color-scheme 的事件监听器,如果是 Vue 的话,将如下代码写入 mounted
函数中。
App.vue
typescript
// App.vue > mounted
import { checkDarkMode } from './util/darkMode'
// 初始化状态
checkDarkMode()
// 将 checkDarkMode 添加为媒体查询"prefers-color-scheme: dark" 的事件监听器
const darkMedia = typeof matchMedia === 'function' && matchMedia('(prefers-color-scheme: dark)')
if (darkMedia && typeof darkMedia.addEventListener === 'function') {
darkMedia.addEventListener('change', checkDarkMode)
}
然后在你喜欢的地方添加一个 明暗模式选择按钮,并吧 setColorMode
绑定上 Click
~
添加具体的黑暗模式样式
完成如上步骤之后,明暗切换就可以正常工作啦,接下来我们要给每个页面添加暗色模式下的 class 样式:
这一步如果使用的是调色板设计的话,会不太一样,这边展示的是单独修改页面样式的情况
less
// pages/xxx.vue > style
// <style lang="less" scoped>
.bg {
background-color: #f9f9f9;
.card {
color: black;
background-color: white;
}
}
// 将 class 定义为 .theme-dark 的子类,实现只在暗色模式下启用的效果。
// 这里可以开启 scoped,不会有影响
.theme-dark .bg {
background-color: #171717;
.card {
background-color: #1d1d1d;
color: #f1f2f5;
}
}